/*
 * Copyright © 2024-2025 Wenze Wei
 *
 * This file is part of StadionOS.
 *
 * This Source Code Form is subject to the terms of the GNU General Public License, v. 2.0.
 * You can obtain a copy of the GPL at
 * https://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 */
 
#ifndef STADIONOS_COMPOSITOR_H
#define STADIONOS_COMPOSITOR_H

#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/un.h>
#include <drm_fourcc.h>
#include <wlr/config.h>
#include <sys/socket.h>
#include <wlr/backend.h>
#include <wlr/util/log.h>
#include <wlr/backend/drm.h>
#include <wlr/backend/multi.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/backend/wayland.h>
#include <wayland-server-core.h>
#include <wlr/backend/session.h>
#include <xkbcommon/xkbcommon.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/render/allocator.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_pointer.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/render/wlr_renderer.h>
#include <linux/input-event-codes.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_xdg_decoration_v1.h>

#include "output.h"
#include "animation.h"

extern struct onatu_compositor global_compositor;

enum layout_mode {
    LAYOUT_TILED,
    LAYOUT_STACKED,
    LAYOUT_FLOAT
};

typedef enum {
    LAYOUT_FLOATING
} WindowLayoutType;

typedef struct onatu_compositor {
    int current_workspace;
    struct wl_list workspaces;
    struct {
        int x_offset;
        int y_offset;
        float scale;
    } multi_monitor_config;
    struct wlr_scene_node *titlebar_node;
    struct wlr_scene_rect *titlebar_bg;
    struct wlr_scene_button *min_btn, *max_btn, *close_btn;
    struct wl_listener titlebar_button_press;
    struct wl_display *display;
    struct wlr_backend *backend;
    struct wlr_renderer *renderer;
    struct wlr_allocator *allocator;

    struct wl_listener new_output;
    struct wl_listener new_input;
    struct wl_listener new_xdg_surface;
    struct wl_listener new_xwayland_surface;

    struct wlr_seat *seat;
    struct wl_list keyboards;
    struct wl_list pointers;

    struct wl_list outputs;
    struct wl_list windows;
    struct wlr_xdg_shell *xdg_shell;
    struct onatu_window *focused_window;
    WindowLayoutType layout_type;

    struct wlr_scene *scene;
    struct wlr_scene_output_layout *scene_layout;
    struct wlr_output_layout *output_layout;
    void (*toggle_tiling)(struct onatu_compositor *);
    void (*minimize_window)(struct onatu_window *window);
    void (*maximize_window)(struct onatu_window *window);
    void (*close_window)(struct onatu_window *window);
    bool allow_scanout;
    enum layout_mode current_layout;

    struct wlr_xwayland *xwayland;
    struct wlr_xwm *xwm;
    struct wlr_xdg_decoration_manager_v1 *decoration_manager;
    struct wl_listener new_decoration;
    FILE *log_file;
    struct wl_event_source *log_monitor;
    bool software_fallback;
    struct wlr_scene_rect *border_rect;
    struct wlr_cursor *cursor;
    int max_height;
    int total_width;
    uint16_t *color_correction_lut;
} onatu_compositor;

struct onatu_window {
    int z_index;
    struct wlr_xdg_surface *xdg_surface;
    struct wlr_scene_node *scene_node;
    bool is_focused;
    bool is_maximized;
    bool is_fullscreen;
    struct {
        bool active;
        float progress;
        int target_x, target_y;
        int target_width, target_height;
        uint32_t start_time;
    } animation;
    struct wl_list link;
    struct wl_listener destroy;
    struct wl_listener map;
    struct wl_listener commit;
    bool is_floating;
    int x, y;
    int width, height;
    char *title;
    struct onatu_compositor *compositor;
    time_t last_commit_time;
    struct {
        int frames_dropped;
        float average_frametime;
    } render_stats;
};

struct touch_point {
    int32_t id;
    double start_x, start_y;
    double current_x, current_y;
    struct timespec timestamp;
    enum { TOUCH_STATE_BEGIN, TOUCH_STATE_UPDATE, TOUCH_STATE_END } state;
    struct wlr_surface *target_surface;
    struct timespec start_time;
};

typedef void (*key_handler)(struct onatu_compositor*);
struct key_binding {
    xkb_keycode_t keycode;
    uint32_t modifiers;
    void (*handler)(struct onatu_compositor*);
};

void compositor_init(struct onatu_compositor *compositor);
int  compositor_run(struct onatu_compositor *compositor);
void compositor_destroy(struct onatu_compositor *compositor);
void keyboard_add(struct onatu_compositor *compositor, struct wlr_input_device *device);
void pointer_add(struct onatu_compositor *compositor, struct wlr_input_device *device);
void focus_window(struct onatu_compositor *compositor, struct onatu_window *window);
void tile_windows(struct onatu_compositor *compositor);
void stack_windows(struct onatu_compositor *compositor);
void float_window(struct onatu_window *window);
void maximize_window(struct onatu_compositor *compositor, struct onatu_window *window);
void unmaximize_window(struct onatu_window *window);

#endif // STADIONOS_COMPOSITOR_H